package org.groovyflow.spring.web;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;

import org.springframework.util.StringUtils;

public abstract class AbstractControllerClassNameFinder implements ControllerClassNameFinder{

	private String requestSuffixToRemove = "";
	private String seperator = "/";
	private String controllerSuffix = "Controller";
	private String controllerPackage = "";
	
	
	public String findClassName(HttpServletRequest request) {
		String ctrlString = findCommandString(request);
		ctrlString = StringUtils.replace(ctrlString, requestSuffixToRemove, "");
		if(ctrlString.startsWith("/"))
			ctrlString = ctrlString.substring(1);
		StringTokenizer tk = new StringTokenizer(ctrlString, this.seperator);
		
		List tokens = new ArrayList();
		while(tk.hasMoreTokens()){
			tokens.add(tk.nextToken());
		}
		if(tokens.isEmpty())
			throw new RuntimeException("Can't find class/method(or block) for " + ctrlString);
		return putClassNameTogether((String) tokens.get(0));
		
	}
	
	protected String putClassNameTogether(String raw){
		String className = raw.substring(0, 1).toUpperCase() + raw.substring(1);
		String dot = (this.controllerPackage == null || this.controllerPackage.equals("")) ? "" : ".";
		className = this.controllerPackage + dot + className + controllerSuffix;
		return className;
	}

	/**
	 * Return the String we use as a basis for figuring out the class name.
	 * We might, for example, use the servletPath, or what comes after the
	 * servlet path.  For example, for '/admin/showUsers.do', we could
	 * possibly return '/admin/showUsers.do', '/admin/showUsers', 'admin',
	 * '/showUsers.do', 'showUsers.do', or 'showUsers'.  In the first three cases our 
	 * <code> findClassName </code> method would end up returning a class name that had '
	 * Admin' in it.  In the second three cases, a class name based on ShowUsers would 
	 * be returned by that method.
	 * <p>
	 * One might also wish to return a command String that uses a request parameter.
	 * @return the string on which to base the class name.
	 */
	protected abstract String findCommandString(HttpServletRequest request);

	
	public String getRequestSuffixToRemove() {
		return requestSuffixToRemove;
	}

	public void setRequestSuffixToRemove(String requestSuffixToRemove) {
		this.requestSuffixToRemove = requestSuffixToRemove;
	}

	public String getSeperator() {
		return seperator;
	}

	public void setSeperator(String seperator) {
		this.seperator = seperator;
	}

	public String getControllerSuffix() {
		return controllerSuffix;
	}

	public void setControllerSuffix(String controllerSuffix) {
		this.controllerSuffix = controllerSuffix;
	}

	public String getControllerPackage() {
		return controllerPackage;
	}

	public void setControllerPackage(String controllerPackage) {
		this.controllerPackage = controllerPackage;
	}

}
